import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:flutter_socket_server/platform_util.dart';
import 'package:flutter_socket_server/screen_util.dart';
import 'package:flutter_socket_server/socket.dart';
import 'package:flutter_socket_server/config/config.dart';

// 展示二维码的弹窗
class ShowQRPage extends StatefulWidget {
  const ShowQRPage({Key key, int port}) : super(key: key);

  @override
  State<ShowQRPage> createState() => _ShowQRPageState();
}

class _ShowQRPageState extends State<ShowQRPage> {
  static const STORAGE_PATH = "/storage/emulated/0/Download/test.zip";

  int mPort;
  String mAddress;
  Socket mClientSocket;
  ServerSocket mServerSocket;
  num mTargetFileLength;
  num mHasTransLength = 0;
  Stream<List<int>> mFileStream;
  int mCurrentProgress;
  int mLastProgress;

  @override
  void initState() {
    super.initState();
    PlatformUtil.localAddress().then((value) {
      print("address:$mAddress");
      mAddress = value;
      getPort().then((value) {
        mPort = value + 1;
        print("port:$mPort");
        setState(() {});
        // 开启服务器
        startServer(mAddress, mPort);
      });
    });
    writeIosFileToSandbox();
  }

  Future<int> getPort() async {
    return await getSafePort(
      Config.chatPortRangeStart,
      Config.chatPortRangeEnd,
    );
  }

  Future<void> writeIosFileToSandbox() async {
    Uint8List bytes;
    if (Platform.isIOS) {
      final byteData = await rootBundle.load('assets/other/test.zip');
      bytes = byteData.buffer
          .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes);
      String appDocPath = await iosFilePath();
      File iosFile = File(appDocPath);
      iosFile.writeAsBytesSync(bytes);
      print('writeAsBytesSync done open ---path ${iosFile.path}');
    }
  }

  iosFilePath() async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path + '/test.zip';
    return appDocPath;
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Material(
        color: Colors.transparent,
        child: Container(
          margin: EdgeInsets.only(left: 10,right: 10,bottom: 10),
          height: 370.w,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10.w),
            color: Colors.white,
          ),
          child: Column(
            children: [
              Expanded(
                child: PageView.builder(
                  itemCount: 1,
                  itemBuilder: (c, i) {
                    print('http://$mAddress:$mPort');
                    return Column(
                      children: [
                        Container(
                          padding: EdgeInsets.all(10.w),
                          child: QrImage(
                            data: '$mAddress:$mPort',
                            version: QrVersions.auto,
                            size: 280.w,
                            foregroundColor:
                                Theme.of(context).colorScheme.onSurface,
                          ),
                        ),
                        SelectableText(
                          '$mAddress:$mPort',
                        ),
                      ],
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> startServer(String localHost, int port) async {
    mServerSocket = await ServerSocket.bind(localHost, port);
    runZoned(() {
      mServerSocket.listen((client) {
        this.mClientSocket = client;
        handleClient(client);
      });
    }, onError: (e) {
      print('Server error: $e');
    });
  }

  void handleClient(Socket client) async {
    if (await Permission.storage.request().isGranted) {
      print("main,Connection from:"
          "${client.remoteAddress.address}:${client.remotePort}");
      File file = File(STORAGE_PATH);
      if (Platform.isIOS) {
        String appDocPath = await iosFilePath();
        file = File(appDocPath);
      }
      mTargetFileLength = file.lengthSync();
      client.listen((Uint8List data) async {
        final request = String.fromCharCodes(data);
        if (request == 'first handle,I want you Send Data') {
          print("main,一次握手成功");
          client.write(
              'second handle,I tell your file length:$mTargetFileLength');
          print("main,发起二次握手");
        } else if (request.startsWith("third handle,ok")) {
          print("main,三次握手成功，开始异步发送数据");
          mFileStream = file.openRead();
          mFileStream.listen(dataHandler,
              onError: fileTransErrorHandler,
              onDone: fileTransDoneHandler,
              cancelOnError: true);
        } else if (request.startsWith("closed")) {
          print("main,客户端关闭了");
        }
      }, onError: errorHandler, onDone: doneHandler, cancelOnError: true);
      if (file.existsSync()) {
        print("main,existsSync ok");
      } else {
        print("main,existsSync no");
      }
    }
  }

  void dataHandler(List<int> data) async {
    mHasTransLength += data.length;
    mCurrentProgress = (100 * mHasTransLength ~/ mTargetFileLength).toInt();
    if (mCurrentProgress != mLastProgress) {
      mLastProgress = mCurrentProgress;
      print("main:已传输百分比为：$mCurrentProgress");
    }
    mClientSocket.add(data);
  }

  // Client socket closed
  void errorHandler(error, StackTrace trace) {
    print("main:Error");
    mFileStream.drain();
  }

  // Client socket done work
  void doneHandler() {
    mServerSocket.close();
    print("main:doneHandler");
  }

  // File read has something wrong
  void fileTransErrorHandler(error, StackTrace trace) {
    print("main:fileTransErrorHandler");
  }

  // File read done work
  void fileTransDoneHandler() {
    mServerSocket.close();
    print("main:fileTransDoneHandler");
  }
}
